﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Card.Security
{
    public class Page : System.Web.UI.Page
    {
        #region 私有变量
        private Passport m_Passport = new Passport();
        /// <summary>
        /// 验证重复提交的标记
        /// </summary>
        private readonly string REFRESH_TICKET_NAME = "___RefreshTicketArray";
        private readonly string HIDDEN_FIELD_NAME = "___RefreshHiddenField";
        private readonly string HIDDEN_PAGE_GUID = "___RefreshPageGuid";
        #endregion

        #region 公共属性
        public Passport Passport
        {
            get { return m_Passport; }
            set { m_Passport = value; }
        }

        private string _UserName = string.Empty;
        public string UserName
        {
            get
            {
                return this._UserName;
            }
        }

        /// <summary>
        /// 为True表示页面刷新,False为正常提交
        /// </summary>
        public bool IsRefresh
        {
            get
            {
                if (IsPostBack && !CheckRefreshToken())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        #endregion

        #region 公共方法
        public Page()
        {
            InitPassport();
        }
        #endregion

        #region 事件

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
        }

        protected override void OnError(EventArgs e)
        {
            string errorMessage = string.Format(@"Url:{0} 
UserName:{1} 
Error:{2}",
                this.Request.Url.ToString(),
                this.Passport.UserName,
                Context.Error.ToString());
            Log.Logger.Error(errorMessage);

            base.OnError(e);
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.UpdateRefreshToken();
        }
        #endregion

        #region 受保护的方法

        #region 操作用户信息
        /// <summary>
        /// 模拟Passport对象
        /// </summary>
        protected virtual void InitPassport()
        {
            if (!this.Passport.IsLogin)
            {
                if (CookieManager.ExistsPassport())
                {
                    this.Passport = CookieManager.GetPassport();
                    this._UserName = CookieManager.GetCookie(CONST.CookieNames.UName);
                }
            }
        }

        /// <summary>
        /// 保存Passport到Cookie
        /// </summary>
        protected virtual void SavePassport()
        {
            CookieManager.AddPassportCookie(this.Passport);
        }

        /// <summary>
        /// 移除Passport
        /// </summary>
        protected virtual void RemovePassport()
        {
            CookieManager.RemovePassport();
        }
        #endregion
        
        #endregion

        #region 私有方法

        #region 重复刷新判断
        /// <summary>
        /// 更新判断重复提交的标识
        /// </summary>
        private void UpdateRefreshToken()
        {
            #region Cookie模式

            //注册页面唯一标识并返回
            string pageGuid = SetCurPageGuid();

            HttpCookie cookie = GetRefreshTicket();

            if (cookie.Values.Count > 0)
            {
                cookie.Values.Remove(pageGuid);
            }

            string submitTime = DateTime.Now.ToString("hhmmss.fffff");
            //当前提交时间保存到隐藏域
            ClientScript.RegisterHiddenField(HIDDEN_FIELD_NAME, submitTime);
            cookie.Values.Clear();
            cookie.Values.Add(pageGuid, submitTime);

            Response.AppendCookie(cookie);

            #endregion
        }

        /// <summary>
        /// 判断是否是刷新提交
        /// </summary>
        /// <returns></returns>
        private bool CheckRefreshToken()
        {
            HttpCookie cookie = GetRefreshTicket();
            string pageGuid = GetCurPageGuid();
            if (cookie.Values.Count > 0)
            {
                bool flag;
                if (cookie.Values[pageGuid] != null)
                    flag = cookie.Values[pageGuid].IndexOf(GetCurSubmitTime()) > -1;
                else
                    flag = true;//防止出现异常,总是可以提交

                return flag;
            }
            return true;
        }

        /// <summary>
        /// 得到已保存的提交时间,没有新建,有返回
        /// </summary>
        /// <returns></returns>
        private HttpCookie GetRefreshTicket()
        {
            #region Cookie模式,返回值为Cookie

            HttpCookie cookie;
            if (Request.Cookies[REFRESH_TICKET_NAME] == null)
            {
                cookie = new HttpCookie(REFRESH_TICKET_NAME);
                Response.AppendCookie(cookie);
            }
            else
            {
                cookie = Request.Cookies[REFRESH_TICKET_NAME];
            }
            return cookie;
            #endregion
        }

        /// <summary>
        /// 获取当前提交时间
        /// </summary>
        /// <returns></returns>
        private string GetCurSubmitTime()
        {
            return Request.Params[HIDDEN_FIELD_NAME] == null ? "" : Request.Params[HIDDEN_FIELD_NAME].ToString();

        }

        /// <summary>
        /// 设置页面唯一标识,通过Guid标识来区分每个页面自己的提交时间
        /// </summary>
        private string SetCurPageGuid()
        {
            string guid;
            if (!IsPostBack)
            {
                if (Request.Params[HIDDEN_PAGE_GUID] == null)
                {
                    guid = System.Guid.NewGuid().ToString();
                }
                else
                {
                    guid = GetCurPageGuid();
                }
            }
            else
            {
                guid = GetCurPageGuid();
            }

            ClientScript.RegisterHiddenField(HIDDEN_PAGE_GUID, guid);
            return guid;
        }

        /// <summary>
        /// 得到当前页面的唯一标识
        /// </summary>
        /// <returns></returns>
        private string GetCurPageGuid()
        {
            return Request.Params[HIDDEN_PAGE_GUID] == null ? "none" : Request.Params[HIDDEN_PAGE_GUID].ToString();
        }
        #endregion

        #endregion

    }
}
